/* 
 * File:   vectorData.h
 * Author: cow
 *
 * Created on June 25, 2011, 10:18 PM
 */

#ifndef UNITBODIES_H
#define	UNITBODIES_H

//includes-----------------------------
#include <vector>
#include <list>
#include <pthread.h>
#include <math.h>
using namespace std;

//defines------------------------------
#define VDIterator vector<VectorPoint*>::iterator
#define VBIterator list<VectorBody*>::iterator

#define MAX_VP_STORAGE 25
#define MAX_VB_STORAGE 10

//prototypes---------------------------
class VectorPoint;
class VectorBody;
class collisionHandler;
class VDataWorld;
template <class pooled> class VPool;
//definitions--------------------------
//----------------------
//VECTORPOINT===========
//----------------------
class VectorPoint {
public:
	//constructor-------
	VectorPoint();
	VectorPoint(float x, float y);
	//Acess-------------
	float distanceTo(VectorPoint* vp);
	int getX();
	int getY();
	bool equals(float x, float y);
	//Manips------------
	void setPoint(float x, float y);
	VectorPoint* dotProduct(VectorPoint* vpoint);
	int determinant(VectorPoint* vp);
	float magnitutde();
	void normalize();
	//operators---------
	VectorPoint operator+(VectorPoint vp);
	VectorPoint operator+(VectorPoint* vp);
	VectorPoint operator-(VectorPoint vp);
	VectorPoint operator-(VectorPoint* vp);
	VectorPoint operator*(const float scalar);
	bool operator==(const VectorPoint& vp);
	void add(VectorPoint* vp);
	void mul(VectorPoint* vp);
	void mul(float scalar);
	void div(VectorPoint* vp);
	void div(float scalar);
	//pool functions----
	static VectorPoint* getCleanVP();
	static VectorPoint* getCleanVP(float x, float y);
	void recycle();
private:
	//vatBlock----------
	static VPool<VectorPoint> pool;
	float X, Y;
	//------------------
};
//----------------------
//VECTORDATA============
//----------------------
class VectorBody {
public:
	//constructors------
	VectorBody();
	VectorBody(vector<VectorPoint*> points);
	VectorBody(list<VectorPoint*> points);
	VectorBody(VectorBody* points);
	~VectorBody();
	//color data--------
	void gColor(float* r, float* g, float* b);
	void sColor(float r, float g, float b);
	//vertex data-------
	void moveVertex(float x, float y, float newX, float newY);
	void addVertex(float x, float y);
	void removeVertex(float x, float y);
	VectorPoint* getCenter();
	VDIterator getBegin();
	VDIterator getEnd();
	//collision---------
	void setOnCollision(collisionHandler* chandler);
	void onCollision(VectorBody* collidesWith);
	bool collidesWith(VectorBody* second);
	bool circleTest(VectorBody* second);
	bool containsPoint(float x, float y);
	//accesors----------
	float getMaxRadius();
	//manipulators------
	void moveCenter(VectorPoint* vp);
	void moveCenter(float x, float y);
	void slideCenter(VectorPoint* vp);
	void slideCenter(float x, float y);
	//pool functions----
	static VectorBody* getCleanVB();
	void recycle();
private:
	float findMaxRange();
	void findCenter();
	//data--------------
	collisionHandler* chandler;
	float colorR, colorG, colorB;
	vector<VectorPoint*> points;
	VectorPoint* center;
	float maxRadius;
	//pool--------------
	static VPool<VectorBody> pool;
};
//----------------------
//COLLISION HANDLER=====
//----------------------
class collisionHandler {
public:
	virtual void onCollision(VectorBody collidedWith) = 0;
};
//----------------------
//VDATA WORLD===========
//----------------------
class VDataWorld {
public:
	//constructors------
	VDataWorld();
	~VDataWorld();
	//detection---------
	void preformCollisions();
	void preformCollisions(VectorBody* vd);
	bool CheckForCollision(VectorBody* vd);
	//data managment----
	void addVData(VectorBody* vd);
	void removeVData(VectorBody* vd);
	void cleanWorld();
	//iterators---------
	VBIterator begining();
	VBIterator end();
private:
	pthread_mutex_t checkMutex;
	list<VectorBody*> bodies;
};
//----------------------
//POOL==================
//----------------------
template <class pooled>
class VPool {
public:
	//constructor-------
	VPool(int maxEntries) : max(maxEntries) { }
	~VPool() {
		while (!pool.empty()) {
			delete pool.front();
			pool.pop_front();
		}
	}
	//get and recycle---
	pooled* getPooledItem() {
		if(pool.empty()) return new pooled();
		pooled* ret = pool.front();
		pool.pop_front();
		return ret;
	}
	void recycleItem(pooled* p) {
		if(p == NULL) return;
		if (pool.size() < max) {
			pool.push_back(p);
		} else {
			delete p;
		}
	}
private:
	int max;
	list<pooled*> pool;
};
#endif	/* UNITBODIES_H */

